package edu.gdei.gdeiassistant.Service.CloudAPI;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import edu.gdei.gdeiassistant.Exception.AuthenticationException.IDCardReversedSideException;
import edu.gdei.gdeiassistant.Exception.AuthenticationException.IDCardVerificationException;
import edu.gdei.gdeiassistant.Exception.PhoneException.*;
import edu.gdei.gdeiassistant.Exception.RecognitionException.RecognitionException;
import edu.gdei.gdeiassistant.Pojo.Entity.Identity;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Service
public class AliYunService {

    @Autowired
    private RestTemplate restTemplate;

    private String aliyunUserId;

    private String aliyunAccessKeyId;

    private String aliyunAccessKeySecret;

    private String aliyun_h5_verifyKey;

    private String official_appCode;

    private String aliyunSMSChinaTemplateCode;

    private String aliyunSMSGlobalTemplateCode;

    @Value("#{propertiesReader['api.aliyun.userid']}")
    public void setAliyunUserId(String aliyunUserId) {
        this.aliyunUserId = aliyunUserId;
    }

    @Value("#{propertiesReader['api.aliyun.accesskey.id']}")
    public void setAliyunAccessKeyId(String aliyunAccessKeyId) {
        this.aliyunAccessKeyId = aliyunAccessKeyId;
    }

    @Value("#{propertiesReader['api.aliyun.accesskey.secret']}")
    public void setAliyunAccessKeySecret(String aliyunAccessKeySecret) {
        this.aliyunAccessKeySecret = aliyunAccessKeySecret;
    }

    @Value("#{propertiesReader['api.aliyun.h5.verifykey']}")
    public void setAliyun_h5_verifyKey(String aliyun_h5_verifyKey) {
        this.aliyun_h5_verifyKey = aliyun_h5_verifyKey;
    }

    @Value("#{propertiesReader['api.aliyun.official.appcode']}")
    public void setOfficial_appCode(String official_appCode) {
        this.official_appCode = official_appCode;
    }

    @Value("#{propertiesReader['api.aliyun.sms.china.templatecode']}")
    public void setAliyunSMSChinaTemplateCode(String aliyunSMSChinaTemplateCode) {
        this.aliyunSMSChinaTemplateCode = aliyunSMSChinaTemplateCode;
    }

    @Value("#{propertiesReader['api.aliyun.sms.global.templatecode']}")
    public void setAliyunSMSGlobalTemplateCode(String aliyunSMSGlobalTemplateCode) {
        this.aliyunSMSGlobalTemplateCode = aliyunSMSGlobalTemplateCode;
    }

    /**
     * OCR识别图片中的数字，返回数字文本串
     *
     * @param image
     * @return
     * @throws RecognitionException
     */
    public String CharacterNumberRecognize(String image) throws RecognitionException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "APPCODE " + official_appCode);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject configure = new JSONObject();
        configure.put("min_size", "16");
        configure.put("output_prob", false);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("configure", configure);
        jsonObject.put("image", image);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange("http://tysbgpu.market.alicloudapi.com/api/predict/ocr_general"
                , HttpMethod.POST, new HttpEntity<>(jsonObject, httpHeaders), JSONObject.class);
        JSONObject result = responseEntity.getBody();
        if (result.containsKey("success") && jsonObject.getBoolean("success")) {
            JSONArray jsonArray = jsonObject.getJSONArray("ret");
            StringBuilder stringBuilder = new StringBuilder();
            for (Object o : jsonArray) {
                String words = ((JSONObject) o).getString("word");
                if (words.matches("^[0-9]*$")) {
                    stringBuilder.append(words);
                }
            }
            return stringBuilder.toString();
        }
        throw new RecognitionException("OCR识别失败");
    }

    /**
     * 识别身份证图片的文字，获取身份证实名信息
     *
     * @return
     */
    public Identity ParseIdentityCard(String image) throws Exception {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "APPCODE " + official_appCode);
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("image", "data:image/jpeg;base64," + image);
        ResponseEntity<String> responseEntity = restTemplate.exchange("https://orcidcard.market.alicloudapi.com/idCardAuto"
                , HttpMethod.POST, new HttpEntity<>(params, httpHeaders), String.class);
        JSONObject result = JSONObject.fromObject(responseEntity.getBody());
        if (result.has("code")) {
            if (result.getString("code").equals("1")) {
                //身份证校验通过，进行解析信息
                Identity identity = new Identity();
                identity.setName(result.getJSONObject("result").getString("name"));
                identity.setCode(result.getJSONObject("result").getString("code"));
                identity.setSex(result.getJSONObject("result").getString("sex"));
                identity.setNation(result.getJSONObject("result").getString("nation"));
                identity.setAddress(result.getJSONObject("result").getString("address"));
                identity.setBirthday(result.getJSONObject("result").getString("birthday"));
                return identity;
            } else if (result.getString("code").equals("2")) {
                //正反面颠倒
                throw new IDCardReversedSideException("身份证正反面颠倒");
            }
        }
        throw new RecognitionException("OCR识别失败");
    }

    /**
     * 身份二要素（姓名+身份证号码）实名制认证
     *
     * @param name
     * @param number
     * @return
     */
    public void VerifyIdentityCard(String name, String number) throws IDCardVerificationException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "APPCODE " + official_appCode);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange("https://safrvcert.market.alicloudapi.com/" +
                "safrv_2meta_id_name/?__userId=" + aliyunUserId + "&identifyNum=" + number + "&userName=" + name +
                "&verifyKey=" + aliyun_h5_verifyKey, HttpMethod.GET, new HttpEntity<>(httpHeaders), JSONObject.class);
        JSONObject jsonObject = responseEntity.getBody();
        if (jsonObject.has("code") && jsonObject.getInt("code") == 200) {
            //校验成功
            return;
        }
        throw new IDCardVerificationException("身份证信息校验不通过");
    }

    /**
     * 身份三要素（姓名+身份证号码+手机号）实名制认证
     *
     * @param name
     * @param number
     * @return
     */
    public void VerifyIdentityCard(String name, String number, String phone) throws IDCardVerificationException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "APPCODE " + official_appCode);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange("https://safrvcert.market.alicloudapi.com/" +
                        "safrv_3meta_id_name_phone/?__userId=" + aliyunUserId + "&identifyNum=" + number +
                        "&mobilePhone=" + phone + "&userName=" + name + "&verifyKey=" + aliyun_h5_verifyKey
                , HttpMethod.GET, new HttpEntity<>(httpHeaders), JSONObject.class);
        JSONObject jsonObject = responseEntity.getBody();
        if (jsonObject.has("code") && jsonObject.getInt("code") == 200) {
            //校验成功
            return;
        }
        throw new IDCardVerificationException("身份证信息校验不通过");
    }

    /**
     * 身份四要素（姓名+身份证号码+手机号+银行卡）实名制认证
     *
     * @param name
     * @param identityNumber
     * @param phone
     * @param cardNumber
     * @return
     */
    public void VerifyIdentityCard(String name, String identityNumber, String phone, String cardNumber) throws IDCardVerificationException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "APPCODE " + official_appCode);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange("https://safrvcert.market.alicloudapi.com/" +
                        "safrv_3meta_id_name_phone/?__userId=" + aliyunUserId + "&identifyNum=" + identityNumber +
                        "&mobilePhone=" + phone + "&userName=" + name + "&bankCard=" + cardNumber + "&verifyKey=" + aliyun_h5_verifyKey
                , HttpMethod.GET, new HttpEntity<>(httpHeaders), JSONObject.class);
        JSONObject jsonObject = responseEntity.getBody();
        if (jsonObject.has("code") && jsonObject.getInt("code") == 200) {
            //校验成功
            return;
        }
        throw new IDCardVerificationException("身份证信息校验不通过");
    }

    /**
     * 国内手机发送短信验证码
     *
     * @param code
     * @param phone
     */
    public void SendChinaPhoneVerificationCodeSMS(int code, String phone) throws ClientException, SendSMSException {
        DefaultProfile profile = DefaultProfile.getProfile("default", aliyunAccessKeyId, aliyunAccessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "default");
        request.putQueryParameter("PhoneNumbers", phone);
        request.putQueryParameter("SignName", "易小助");
        request.putQueryParameter("TemplateCode", aliyunSMSChinaTemplateCode);
        request.putQueryParameter("TemplateParam", "{code:\"" + code + "\"}");
        CommonResponse response = client.getCommonResponse(request);
        JSONObject result = JSONObject.fromObject(response.getData());
        if (result.containsKey("Code")) {
            if (result.getString("Code").equals("OK")) {
                //发送成功
            } else if (result.getString("Code").equals("isv.MOBILE_NUMBER_ILLEGAL")) {
                //不合法的手机号
                throw new IllegalPhoneNumberException();
            } else if (result.getString("Code").equals("VALVE:M_MC")) {
                //分钟请求次数过多
                throw new MinuteFrequencyLimitException();
            } else if (result.getString("Code").equals("VALVE:H_MC")) {
                //小时请求次数过多
                throw new HourFrequencyLimitException();
            } else if (result.getString("Code").equals("VALVE:D_MC")) {
                //天请求次数过多
                throw new DayFrequencyLimitException();
            } else {
                //其他错误
                throw new SendSMSException();
            }
        }
    }

    /**
     * 港澳台和国际手机发送短信验证码
     *
     * @param code
     * @param areaCode
     * @param phone
     * @throws ClientException
     */
    public void SendGlobalPhoneVerificationCodeSMS(int code, int areaCode, String phone) throws ClientException, SendSMSException {
        DefaultProfile profile = DefaultProfile.getProfile("default", aliyunAccessKeyId, aliyunAccessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "default");
        request.putQueryParameter("PhoneNumbers", areaCode + phone);
        request.putQueryParameter("SignName", "易小助");
        request.putQueryParameter("TemplateCode", aliyunSMSGlobalTemplateCode);
        request.putQueryParameter("TemplateParam", "{code:\"" + code + "\"}");
        CommonResponse response = client.getCommonResponse(request);
        JSONObject result = JSONObject.fromObject(response.getData());
        if (result.containsKey("Code")) {
            if (result.getString("Code").equals("OK")) {
                //发送成功
            } else if (result.getString("Code").equals("isv.MOBILE_NUMBER_ILLEGAL")) {
                //不合法的手机号
                throw new IllegalPhoneNumberException();
            } else if (result.getString("Code").equals("VALVE:M_MC")) {
                //分钟请求次数过多
                throw new MinuteFrequencyLimitException();
            } else if (result.getString("Code").equals("VALVE:H_MC")) {
                //小时请求次数过多
                throw new HourFrequencyLimitException();
            } else if (result.getString("Code").equals("VALVE:D_MC")) {
                //天请求次数过多
                throw new DayFrequencyLimitException();
            } else {
                //其他错误
                throw new SendSMSException();
            }
        }
    }
}
